home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume25 / ted / part01 next >
Encoding:
Text File  |  1991-11-06  |  54.9 KB  |  1,626 lines

  1. Newsgroups: comp.sources.misc
  2. From: dan%step.uucp@uunet.uu.net (Daniel Weaver)
  3. Subject:  v25i026:  ted - Terminfo/termcap test program, Part01/07
  4. Message-ID: <csm-v25i026=ted.221456@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: 850d0c6ae14fe275562f46a2e990709e
  6. Date: Wed, 6 Nov 1991 04:15:26 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: dan%step.uucp@uunet.uu.net (Daniel Weaver)
  10. Posting-number: Volume 25, Issue 26
  11. Archive-name: ted/part01
  12. Environment: UNIX
  13.  
  14. Terminfo/termcap test program (TED).
  15.  
  16.    The purpose of this program is to verify the correctness of
  17. terminfo's/termcaps and to calculate the pads needed for each
  18. capability.  This program is not designed to test curses and
  19. therefore uses as little of curses as possible.  TED was originally
  20. written to test terminfo's and termcaps were added as an after
  21. thought.  Various places within the program I make the (decidedly
  22. wrong) assumption that termcaps have a one to one mapping with
  23. terminfo's.  Due to the lack of standardization for termcaps
  24. I see no other reasonable solution.
  25.  
  26. See the README for more information.
  27.  
  28. #! /bin/sh
  29. # This is a shell archive.  Remove anything before this line, then feed it
  30. # into a shell via "sh file" or similar.  To overwrite existing files,
  31. # type "sh file -c".
  32. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  33. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  34. # If this archive is complete, you will see the following message at the end:
  35. #        "End of archive 1 (of 7)."
  36. # Contents:  README fun.c
  37. # Wrapped by dan@step on Fri Nov  1 11:28:23 1991
  38. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  39. if test -f 'README' -a "${1}" != "-c" ; then 
  40.   echo shar: Will not clobber existing file \"'README'\"
  41. else
  42. echo shar: Extracting \"'README'\" \(6979 characters\)
  43. sed "s/^X//" >'README' <<'END_OF_FILE'
  44. X
  45. XTerminfo/termcap test program (TED).
  46. X
  47. X   The purpose of this program is to verify the correctness of
  48. Xterminfo's/termcaps and to calculate the pads needed for each
  49. Xcapability.  This program is not designed to test curses and
  50. Xtherefore uses as little of curses as possible.  TED was originally
  51. Xwritten to test terminfo's and termcaps were added as an after
  52. Xthought.  Various places within the program I make the (decidedly
  53. Xwrong) assumption that termcaps have a one to one mapping with
  54. Xterminfo's.  Due to the lack of standardization for termcaps
  55. XI see no other reasonable solution.
  56. X
  57. XBuilding terminfo's from scratch.
  58. X   I have tried to structure the program in such a way as to
  59. Xfacilitate the creation of new terminfo's.  The tests done at the
  60. Xbeginning of the program are assumed to be correct later in the code.
  61. XTED displays the number of lines and columns as part of its initial
  62. Xoutput.  If these values are wrong a large number of tests will
  63. Xfail or give incorrect results.
  64. X
  65. X   The following options are designed to help create new terminfo's.
  66. X
  67. X    -e  Echo test.  All data typed from the keyboard will be
  68. X    echoed back to the terminal.  Control characters are
  69. X    not translated to the up arrow format but are sent
  70. X    as control characters.  This allows the user to test an
  71. X    escape sequence and see what it actually does.
  72. X
  73. X    -S  Status report test.  This test acts much like the echo test
  74. X    but characters that are sent from the terminal more than
  75. X    one character after a carriage return will be expanded
  76. X    to the up arrow format.  For example on a standard ANSI
  77. X    terminal you may type:
  78. X        CR ESC [ c
  79. X    and the response will be echoed as:
  80. X        ^[ [ ? 6 c
  81. X
  82. X    -g  ANSI sgr display.  This test assumes you have an ANSI terminal.
  83. X    It displays the sgr number using that sgr to write the text.
  84. X    This helps the programmer know which of the sgr modes are
  85. X    actually implemented by the terminal.
  86. X       Some terminals (such as Tektronix color) use the private
  87. X    use characters to augment the functionality of the sgr command.
  88. X    These private use characters may be interjected into the
  89. X    escape sequence by typing the character ( <, =, >, ? ) after
  90. X    the original display has been shown.
  91. X
  92. X    -A  ANSI status report test.  This test queries the terminal in
  93. X    standard ANSI fashion (read VT-100).  The results of this test
  94. X    may be useful in helping to determine what options are
  95. X    available.
  96. X
  97. XVerifying correctness.
  98. X
  99. X    After the terminfo has been built TED should be used to verify
  100. Xthat it is correct.  The general philosophy of the program is to
  101. Xsend something to the terminal and ask the user to check its validity.
  102. XFor the specific capability tests (using the -p option) the program
  103. Xwill try to make it easy for the user to see if the cap is doing the
  104. Xcorrect thing.  For example the "Clear to end of line" test will
  105. Xuse the cap on all but one of the lines, and on the last line, the
  106. Xprogram will print what the values should be.
  107. X
  108. XDetermining pad times.
  109. X
  110. X    The key to determining pad times is to find out what effective
  111. Xbaud rate the terminal is running at.  The effective baud rate
  112. Xis the number of characters that the terminal can accept without
  113. Xhandshaking and without loosing data.  This rate is frequently
  114. Xless than the actual baud rate on the RS-232 line.
  115. X    TED uses the effective baud rate to judge the duration of the
  116. Xtest and how much a particular escape sequence will perturb the
  117. Xterminal.
  118. X    The best way to time the terminal is to use some kind of
  119. Xhandshake such as ENQ/ACK.  With this handshake the program
  120. Xsends an ENQ and waits for an ACK.  Many terminals can be setup
  121. Xto do this (although it is by no means universal).  TED will
  122. Xfunction much better if you can setup your terminal to do ENQ/ACK.
  123. XThe more common Control S Control Q handshake cannot be used for
  124. Xthis purpose because it does not tell me if the terminal is idle.
  125. X    Each pad test has a few variables that can help verify the
  126. Xcorrectness of the pad counts.  After a test is completed the
  127. Xprogram will type "Done." followed by the names of the cap actually
  128. Xtested.  At this point the following characters may be input
  129. Xto change how the test was run and permit rerunning of the test.
  130. X   d - double the number of lines (or characters) effected.
  131. X   h - half the number of lines (or characters) effected.
  132. X   n - goto the next test
  133. X   p - edit the pad counts
  134. X   r - rerun the test
  135. X   < - make the test shorter
  136. X   > - make the test longer
  137. X   ? - redisplay the Done message
  138. X   <number> - change the number of lines (characters) effected to be
  139. X              this number.
  140. X   <cr> - continue with next test
  141. X
  142. X    The results of the pad tests will be written to a file.  The
  143. Xfilename will be ted.$TERM (where $TERM is your environment variable).
  144. XThe data contained within the file should not be taken as gospel.
  145. XSome of the data (such as for ich1/dch1) is not placed in the file
  146. Xand can only be obtained by watching the display.  System load
  147. Xwill also effect the results.
  148. X    Not all variables make sense to all tests.  For example the number
  149. Xof lines effected has no effect of clear screen.  Once again I must
  150. Xwarn you about taking this as gospel.  Each program has the option
  151. Xof using "Number of lines effected" or ignoring it.  So what works
  152. Xfor TED and 6 other programs may fail on your favorite spread sheet.
  153. X
  154. XThe .termdefs file
  155. X
  156. X   TED uses the .termdefs file in $HOME to read options for a specific
  157. Xterminal.  The file has the format:
  158. X   terminal-name options ...
  159. XThe options may be any option that is normally passed on the command line.
  160. XThe best use for the file is to hold the enquire/acknoledge sequences
  161. Xneeded for a specific terminal.  The default enquire/acknoledge sequence
  162. Xis conreol E (ENQ) and control F (ACK).  This could be represented by
  163. Xthe command line options -Q 5 -T 6 -j 0.  The default sequence works with
  164. Xa Wyse 50 but not a VT-100.  The VT-100 uses <esc> [ c or <esc> Z to
  165. Xenquire and the response string may be rather long but ends in a c.
  166. XThe -Q option allows you to set the enquire string to any ASCII characters.
  167. XThe -Q option is followed by a list of characters entered as decimal
  168. Xnumbers.  For example <esc> [ c becomes -Q 27 91 99 0.  The zero
  169. Xterminates the string.  The acknoledge string ends with a c.  This
  170. Xis described by -T 99.  The number of characters that have to be thrown
  171. Xaway is described by -j 6.  The throw away characters, which I call
  172. Xjunk characters, should be large enough to handle the longest response
  173. Xgiven by the enquire string.  It is better to make this number too large
  174. Xthan too small.
  175. X   The terminal names are scanned with a first fit algorithm.  Therefore
  176. Xlonger names should appear first.  If your terminal type is vt100-w and
  177. Xvt100-w is not in the file, then TED will use vt100 (if it is in the file).
  178. XIf both vt100-w and vt100 are used in the file then vt100-w should be
  179. Xfirst.
  180. X   Here is an example of a .termdefs file:
  181. X
  182. X    wy50 +nx
  183. X    kermit -Q 27 90 0 -T 75 -j 2
  184. X    vt100-w -Q 27 91 99 0 -T 99 -j 6
  185. X    vt100 -Q 27 91 99 0 -T 99 -j 6
  186. X    xtalk -Q 27 91 99 0 -T 99 -j 6
  187. X
  188. END_OF_FILE
  189. if test 6979 -ne `wc -c <'README'`; then
  190.     echo shar: \"'README'\" unpacked with wrong size!
  191. fi
  192. # end of 'README'
  193. fi
  194. if test -f 'fun.c' -a "${1}" != "-c" ; then 
  195.   echo shar: Will not clobber existing file \"'fun.c'\"
  196. else
  197. echo shar: Extracting \"'fun.c'\" \(44721 characters\)
  198. sed "s/^X//" >'fun.c' <<'END_OF_FILE'
  199. X/*
  200. X** This software is Copyright (c) 1991 by Daniel Weaver.
  201. X**
  202. X** Permission is hereby granted to copy, distribute or otherwise
  203. X** use any part of this package as long as you do not try to make
  204. X** money from it or pretend that you wrote it.  This copyright
  205. X** notice must be maintained in any copy made.
  206. X**
  207. X** Use of this software constitutes acceptance for use in an AS IS
  208. X** condition. There are NO warranties with regard to this software.
  209. X** In no event shall the author be liable for any damages whatsoever
  210. X** arising out of or in connection with the use or performance of this
  211. X** software.  Any use of this software is at the user's own risk.
  212. X**
  213. X**  If you make modifications to this software that you feel
  214. X**  increases it usefulness for the rest of the community, please
  215. X**  email the changes, enhancements, bug fixes as well as any and
  216. X**  all ideas to me. This software is going to be maintained and
  217. X**  enhanced as deemed necessary by the community.
  218. X*/
  219. X/* test the function keys on the terminal */
  220. X
  221. X#include "curses.h"
  222. X#include "ted.h"
  223. X
  224. X#define MAX_MODES 256
  225. X
  226. Xextern char *malloc();
  227. X
  228. X/* scan code externals */
  229. Xextern int scan_max;  /* length of longest scan code */
  230. Xextern char **scan_up, **scan_down, **scan_name;
  231. Xextern int *scan_tested, *scan_length;
  232. X
  233. X/* local definitions */
  234. Xstatic char *fk_name[MAX_STRINGS];
  235. Xstatic char *fkval[MAX_STRINGS];
  236. Xstatic char *fk_label[MAX_STRINGS];  /* function key labels (if any) */
  237. Xstatic int fk_tested[MAX_STRINGS];
  238. Xstatic int fkmax = 1;  /* length of longest key */
  239. Xstatic int got_labels = 0;  /* true if we have some labels */
  240. Xstatic int key_count = 0;
  241. Xstatic int end_state;
  242. X
  243. X/* unknown function keys */
  244. X#define MAX_FK_UNK 50
  245. Xstatic char *fk_unknown[MAX_FK_UNK];
  246. Xstatic int fk_length[MAX_FK_UNK];
  247. Xstatic int funk;
  248. X
  249. Xstatic char default_bank[] = "\033(B\017";
  250. Xstatic char *puc[] = {"", "<", "=", ">", "?", 0};
  251. Xstatic int private_use, ape, terminal_class, got_escape;
  252. Xstatic short ansi_value[256];
  253. Xstatic char ansi_buf[512], pack_buf[512];
  254. Xstatic char *ach, *pch;
  255. X
  256. Xstruct ansi_reports {
  257. X   int lvl, final;
  258. X   char *text;
  259. X   char *request;
  260. X};
  261. X
  262. Xstatic struct ansi_reports report_list[] = {
  263. X   0, 'c', "(DA) Primary device attributes", "\033[0c",
  264. X   1,  0,  "(DSR) Terminal status", "\033[5n",
  265. X   1, 'R', "(DSR) Cursor position", "\033[6n",
  266. X   62, 0, "(DA) Secondary device attributes", "\033[>0c",
  267. X   62, 0, "(DSR) Printer status", "\033[?15n",
  268. X   62, 0, "(DSR) Function key definition", "\033[?25n",
  269. X   62, 0, "(DSR) Keyboard language", "\033[?26n",
  270. X   63, 0, "(DECRQSS) Data destination", "\033P$q$}\033\\",
  271. X   63, 0, "(DECRQSS) Status line type", "\033P$q$~\033\\",
  272. X   63, 0, "(DECRQSS) Erase attribute", "\033P$q\"q\033\\",
  273. X   63, 0, "(DECRQSS) Personality", "\033P$q\"p\033\\",
  274. X   63, 0, "(DECRQSS) Top and bottom margins", "\033P$qr\033\\",
  275. X   63, 0, "(DECRQSS) Character attributes", "\033P$qm\033\\",
  276. X   63, 0, "(DECRQSS) Illegal request", "\033P$q@\033\\",
  277. X   63, 0, "(DECRQUPSS) User pref suplemental set", "\033[&u",
  278. X   63, 0, "(DECRQPSR) Cursor information", "\033[1$w",
  279. X   63, 0, "(DECRQPSR) Tab stop information", "\033[2$w",
  280. X   64, 0, "(DA) Tertiary device attributes", "\033[=0c",
  281. X   64, 0, "(DSR) Extended cursor position", "\033[?6n",
  282. X   64, 0, "(DSR) Macro space", "\033[?62n",
  283. X   64, 0, "(DSR) Memory checksum", "\033[?63n",
  284. X   64, 0, "(DSR) Data integrity", "\033[?75n",
  285. X   64, 0, "(DSR) Multiple session status", "\033[?85n",
  286. X   64, 0, "(DECRQSS) Attribute change extent", "\033P$q*x\033\\",
  287. X   64, 0, "(DECRQSS) Columns per page", "\033P$q$|\033\\",
  288. X   64, 0, "(DECRQSS) Lines per page", "\033P$qt\033\\",
  289. X   64, 0, "(DECRQSS) Lines per screen", "\033P$q*|\033\\",
  290. X   64, 0, "(DECRQSS) Left and right margins", "\033P$qs\033\\",
  291. X   64, 0, "(DECRQSS) Local functions", "\033P$q+q\033\\",
  292. X   64, 0, "(DECRQSS) Local function key control", "\033P$q=}\033\\",
  293. X   64, 0, "(DECRQSS) Select modifier key reporting", "\033P$q+r\033\\",
  294. X   64, 0, "(DECRQDE) Window report", "\033[\"v",
  295. X   0, 0, 0, 0};
  296. X
  297. Xstruct request_control {
  298. X   char *text;
  299. X   char *expect;
  300. X   char *request;
  301. X   char *set_mode;
  302. X   char *reset_mode;
  303. X};
  304. X
  305. X/* Request control function selection or setting */
  306. Xstruct request_control rqss[] = {
  307. X    "Data sent to screen",    "0", "$}", "\033[0$}", 0,
  308. X    "Data sent to disabled status line", "0", "$}",
  309. X        "\033[0$~\033[1$}", "\033[0$}",
  310. X    "Data sent to enabled status line", "1", "$}",
  311. X        "\033[2$~\033[1$}", "\033[0$}",
  312. X    "Disbale status line",    "0", "$~", "\033[0$~", 0,
  313. X    "Top status line",        "1", "$~", "\033[1$~", 0,
  314. X    "Bottom status line",    "2", "$~", "\033[2$~", 0,
  315. X    "Eraseable character",    "0", "\"q", "\033[0\"q", 0,
  316. X    "Noneraseable character",    "1", "\"q", "\033[1\"q", "\033[0\"q",
  317. X    "Top and bottom margins",    "3;10", "r", "\0337\033[3;10r",
  318. X    "\033[r\0338",
  319. X    "Top and bottom margins",    "default", "r", "\0337\033[r", "\0338",
  320. X    "Character attributes, dim, bold", "1", "m", "\033[2;1m", "\033[m",
  321. X    "Character attributes, bold, dim", "2", "m", "\033[1;2m", "\033[m",
  322. X    "Character attributes, under, rev",    "4;7", "m", "\033[4;7m", "\033[m",
  323. X    "Character attributes, color", "35;42", "m", "\033[35;42m", "\033[m",
  324. X    "All character attributes",    "", "m", "\033[1;2;3;4;5;6;7;8;9m",
  325. X    "\033[m",
  326. X    0, 0, 0, 0, 0
  327. X};
  328. X
  329. Xstatic void
  330. Xkeys_tested(first_time, hex_output)
  331. Xint first_time, hex_output;
  332. X   {  /* display a list of the keys not tested */
  333. X      int i, l;
  334. X      char outbuf[256];
  335. X
  336. X      put_clear();
  337. X      tty_set();
  338. X      if (tty_can_sync) (void) tty_sync_error();
  339. X      if (got_labels)
  340. X         {
  341. X            putln("Function key labels:");
  342. X               for (i = 0; i < key_count; ++i) {
  343. X                  if (fk_label[i])
  344. X                     {
  345. X                        sprintf(outbuf, "%s %s",
  346. X                           fk_name[i] ? fk_name[i] : "??", fk_label[i]);
  347. X                        put_columns(outbuf, strlen(outbuf), 16);
  348. X                     }
  349. X               }
  350. X            put_newlines(2);
  351. X         }
  352. X      if (funk)
  353. X         {
  354. X            putln("The following keys are not defined:");
  355. X               for (i = 0; i < funk; ++i) {
  356. X                  put_columns(fk_unknown[i], fk_length[i], 16);
  357. X               }
  358. X            put_mode(exit_attribute_mode);
  359. X            put_newlines(2);
  360. X         }
  361. X      if (first_time) putln("The following keys are defined:");
  362. X      else putln("The following keys have not been tested:");
  363. X      if (scan_mode)
  364. X         for (i = 0; scan_down[i]; i++) {
  365. X            if (!scan_tested[i])
  366. X               {
  367. X                  if (hex_output)
  368. X                     strcpy(outbuf, hex_expand_to(scan_down[i], 3));
  369. X                  else strcpy(outbuf, expand(scan_down[i]));
  370. X                  l = expand_chars;
  371. X                  if (hex_output)
  372. X                     strcat(outbuf, hex_expand_to(scan_up[i], 3));
  373. X                  else strcat(outbuf, expand(scan_up[i]));
  374. X                  expand_chars += l;
  375. X                  l = strlen(scan_name[i]);
  376. X                  if (((char_count + 16) & ~15) +
  377. X                     ((expand_chars + 7) & ~7) + l >= columns)
  378. X                     put_crlf();
  379. X                  else
  380. X                  if (char_count) putchp(' ');
  381. X                  put_columns(outbuf, expand_chars, 16);
  382. X                  put_columns(scan_name[i], l, 8);
  383. X               }
  384. X         }
  385. X      else
  386. X         for (i = 0; i < key_count; i++) {
  387. X            if (!fk_tested[i])
  388. X               {
  389. X                  if (hex_output)
  390. X                     strcpy(outbuf, hex_expand_to(fkval[i], 3));
  391. X                  else strcpy(outbuf, expand(fkval[i]));
  392. X                  l = strlen(fk_name[i]);
  393. X                  if (((char_count + 16) & ~15) +
  394. X                     ((expand_chars + 7) & ~7) + l >= columns)
  395. X                     put_crlf();
  396. X                  else
  397. X                  if (char_count) putchp(' ');
  398. X                  put_columns(outbuf, expand_chars, 16);
  399. X                  put_columns(fk_name[i], l, 8);
  400. X               }
  401. X         }
  402. X      put_newlines(2);
  403. X   }
  404. X
  405. X
  406. X#ifdef TESTCAP
  407. Xvoid
  408. Xenter_lab(key_name, key_value, lab_name, lab_value)
  409. Xchar *key_name, *key_value, *lab_name, *lab_value;
  410. X   {  /* enter a label.  Called by getcap() */
  411. X      int j;
  412. X
  413. X      cap_test(key_name);
  414. X      cap_test(lab_name);
  415. X      /* ignore labels without function key values */
  416. X      if (key_value)
  417. X         {
  418. X            j = strlen(key_value);
  419. X            fkmax = fkmax > j ? fkmax : j;
  420. X            fkval[key_count] = key_value;
  421. X            fk_tested[key_count] = 0;
  422. X            fk_name[key_count] = key_name;
  423. X            fk_label[key_count++] = lab_value;
  424. X            if (lab_value) got_labels = TRUE;
  425. X         }
  426. X   }
  427. X#endif
  428. X
  429. X
  430. Xvoid
  431. Xenter_key(name, value)
  432. Xchar *name, *value;
  433. X   {  /* enter a function key.  Also called by getcap() */
  434. X      int j;
  435. X
  436. X#ifdef TESTCAP
  437. X      cap_test(name);
  438. X#else
  439. X      can_test(name);
  440. X#endif
  441. X      if (value)
  442. X         {
  443. X            j = strlen(value);
  444. X            fkmax = fkmax > j ? fkmax : j;
  445. X            /* do not permit duplicates */
  446. X               for (j = 0; j < key_count; j++) {
  447. X                  if (!strcmp(fk_name[j], name)) return;
  448. X               }
  449. X            fkval[key_count] = value;
  450. X            fk_tested[key_count] = 0;
  451. X            fk_label[key_count] = NULL;
  452. X            fk_name[key_count++] = name;
  453. X         }
  454. X   }
  455. X
  456. X
  457. Xstatic void
  458. Xfind_keys()
  459. X   {  /* find out which function keys are defined */
  460. X#ifndef TESTCAP
  461. X      char **string_base;
  462. X      char *fkey_number[MAX_STRINGS];  /* function key number */
  463. X      char *fkey_label[MAX_STRINGS];  /* function key labels */
  464. X      int i, j, k;
  465. X
  466. X      string_base = &back_tab;
  467. X         for (i = j = 0; strnames[i]; i++) {
  468. X            if (*string_base)
  469. X               if (strncmp(strnames[i], "lf", 2) == 0)
  470. X                  {
  471. X                     fkey_number[j] = strnames[i];
  472. X                     fkey_label[j++] = *string_base;
  473. X                  }
  474. X               else
  475. X               if (strnames[i][0] == 'k')
  476. X                  enter_key(strnames[i], *string_base);
  477. X            if (string_base == &prtr_non)
  478. X#ifdef SVR3
  479. X               string_base = &char_padding;
  480. X#else
  481. X               break;
  482. X#endif
  483. X            else string_base++;
  484. X         }
  485. X      /* match the labels to the function keys */
  486. X         for (i = 0; i < j; i++) {
  487. X               for (k = 0; k < key_count; k++)
  488. X                  if (!strcmp(&fkey_number[i][1], &fk_name[k][1])) {
  489. X                     fk_label[k] = fkey_label[i];
  490. X                     got_labels = TRUE;
  491. X                     break;
  492. X                  }
  493. X         }
  494. X#endif
  495. X   }
  496. X
  497. X
  498. Xstatic void
  499. Xfresh_line()
  500. X   {  /* clear the line for a new fumction key line */
  501. X      if (over_strike) put_crlf();
  502. X      else
  503. X         {
  504. X            put_cr();
  505. X            if (clr_eol) putp(clr_eol);
  506. X            else put_str("                    \r");
  507. X         }
  508. X   }
  509. X
  510. X
  511. Xstatic int
  512. Xend_funky(ch)
  513. X   {  /* return true if this is the end */
  514. X      switch (ch) {
  515. X         case 'e':
  516. X         case 'E':
  517. X            end_state = 'e';
  518. X            break;
  519. X         case 'n':
  520. X         case 'N':
  521. X            if (end_state == 'e') end_state = 'n';
  522. X            else end_state = 0;
  523. X            break;
  524. X         case 'd':
  525. X         case 'D':
  526. X            if (end_state == 'n') end_state = 'd';
  527. X            else end_state = 0;
  528. X            break;
  529. X         case 'l':
  530. X         case 'L':
  531. X            if (end_state == 'l') end_state = '?';
  532. X            else end_state = 'l';
  533. X            break;
  534. X         default:
  535. X            end_state = 0;
  536. X            break;
  537. X      }
  538. X      return end_state == 'd';
  539. X   }
  540. X
  541. X
  542. Xstatic int
  543. Xfound_match(s, hx, cc)
  544. Xchar *s;
  545. Xint hx, cc;
  546. X   {  /* return true if this string is a match */
  547. X      int j, f;
  548. X      char outbuf[256];
  549. X
  550. X      if (!*s) return 0;
  551. X      if (scan_mode)
  552. X         for (j = f = 0; scan_down[j]; j++) {
  553. X            if (scan_length[j] == 0) continue;
  554. X            if (!strncmp(s, scan_down[j], scan_length[j]))
  555. X               {
  556. X                  if (!f)
  557. X                     {  /* first match */
  558. X                        put_cr();
  559. X                        if (hx) put_str(hex_expand_to(s, 10));
  560. X                        else put_str(expand_to(s, 10));
  561. X                        f = 1;
  562. X                     }
  563. X                  (void) end_funky(scan_name[j][0]);
  564. X                  put_str(" ");
  565. X                  put_str(scan_name[j]);
  566. X                  scan_tested[j] = 1;
  567. X                  s += scan_length[j];
  568. X                  if (strncmp(s, scan_up[j], scan_length[j]))
  569. X                     {
  570. X                        put_str(" scan down");
  571. X                     }
  572. X                  else s += scan_length[j];
  573. X                  if (!*s) break;
  574. X                  j = -1;
  575. X               }
  576. X            if (!strncmp(s, scan_up[j], scan_length[j]))
  577. X               {
  578. X                  if (!f)
  579. X                     {  /* first match */
  580. X                        put_cr();
  581. X                        if (hx) put_str(hex_expand_to(s, 10));
  582. X                        else put_str(expand_to(s, 10));
  583. X                        f = 1;
  584. X                     }
  585. X                  put_str(" ");
  586. X                  put_str(scan_name[j]);
  587. X                  put_str(" scan up");
  588. X                  s += scan_length[j];
  589. X                  if (!*s) break;
  590. X                  j = -1;
  591. X               }
  592. X         }
  593. X      else
  594. X         for (j = f = 0; j < key_count; j++) {
  595. X            if (!strcmp(s, fkval[j]))
  596. X               {
  597. X                  if (!f)
  598. X                     {  /* first match */
  599. X                        put_cr();
  600. X                        if (hx) put_str(hex_expand_to(s, 10));
  601. X                        else put_str(expand_to(s, 10));
  602. X                        f = 1;
  603. X                     }
  604. X                  sprintf(outbuf, " (%s)", fk_name[j]);
  605. X                  put_str(outbuf);
  606. X                  if (fk_label[j])
  607. X                     {
  608. X                        sprintf(outbuf, " <%s>", fk_label[j]);
  609. X                        put_str(outbuf);
  610. X                     }
  611. X                  fk_tested[j] = 1;
  612. X               }
  613. X         }
  614. X      if (end_state == '?')
  615. X         {
  616. X            keys_tested(0, hx);
  617. X            tty_raw(cc, char_mask);
  618. X            end_state = 0;
  619. X         }
  620. X      return f;
  621. X   }
  622. X
  623. X
  624. Xstatic int
  625. Xfound_exit(keybuf, hx, cc)
  626. Xchar *keybuf;
  627. Xint hx, cc;
  628. X   {  /* return true if the user wants to exit */
  629. X      int j, k;
  630. X      char *s;
  631. X
  632. X
  633. X      if (scan_mode)
  634. X         {
  635. X            if (*keybuf == '\0') return TRUE;
  636. X         }
  637. X      else
  638. X         {
  639. X            /* break is a special case */
  640. X            if (*keybuf == '\0')
  641. X               {
  642. X                  fresh_line();
  643. X                  tty_set();
  644. X                  ptext("Hit X to exit");
  645. X                  if (wait_here() == 'X') return TRUE;
  646. X                  keys_tested(0, hx);
  647. X                  tty_raw(cc, char_mask);
  648. X                  return FALSE;
  649. X               }
  650. X            /* is this the end? */
  651. X               for (k = 0; j = (keybuf[k] & STRIP_PARITY); k++) {
  652. X                  if (end_funky(j)) return TRUE;
  653. X               }
  654. X
  655. X            j = TRUE;  /* does he need an updated list? */
  656. X               for (k = 0; keybuf[k]; k++)
  657. X                  j &= (keybuf[k] & STRIP_PARITY) == '?';
  658. X            if (j || end_state == '?')
  659. X               {
  660. X                  keys_tested(0, hx);
  661. X                  tty_raw(cc, char_mask);
  662. X                  end_state = 0;
  663. X                  return FALSE;
  664. X               }
  665. X         }
  666. X
  667. X      put_cr();
  668. X      if (hx) s = hex_expand_to(keybuf, 10);
  669. X      else s = expand_to(keybuf, 10);
  670. X      sprintf(temp, "%s Unknown", s);
  671. X      put_str(temp);
  672. X         for (j = 0; j < MAX_FK_UNK; j++) {
  673. X            if (j == funk)
  674. X               {
  675. X                  fk_length[funk] = expand_chars;
  676. X                  if (fk_unknown[funk] = malloc(strlen(s) + 1))
  677. X                      strcpy(fk_unknown[funk++], s);
  678. X                  break;
  679. X               }
  680. X            if (fk_length[j] == expand_chars)
  681. X               if (!strcmp(fk_unknown[j], s)) break;
  682. X         }
  683. X      return FALSE;
  684. X   }
  685. X
  686. X
  687. Xtest_funky(hex_output)
  688. Xint hex_output;
  689. X   {
  690. X      int i, j, k, len, fk;
  691. X      char outbuf[256];
  692. X      char keybuf[256];
  693. X
  694. X      find_keys();
  695. X      if (stop_testing)
  696. X         {
  697. X            can_test("(km)(smm)(rmm)");
  698. X#ifdef SVR3
  699. X            can_test("(nlab)(lw)(lh)(smln)(plm)(rmln)");
  700. X#endif
  701. X#ifndef TESTCAP
  702. X            can_test("(pfx)(pfloc)");
  703. X#endif
  704. X            return;
  705. X         }
  706. X      if (tty_can_sync == 1) verify_time();
  707. X      if (keypad_xmit) putp(keypad_xmit);
  708. X      keys_tested(1, hex_output);  /* also clears screen */
  709. X      ptextln("Hit any function key.  Type 'end' to quit.  Type ? to update the display.");
  710. X      put_crlf();
  711. X      keybuf[0] = '\0';
  712. X      end_state = 0;
  713. X      if (scan_mode) fkmax = scan_max;
  714. X#ifdef WAIT_MODE
  715. X      sprintf(temp, "All function keys are assumed to be %d characters long.  You must pad shorter keys with blanks.", fkmax);
  716. X      ptextln(temp);
  717. X      /* use this code if your OS can not tell if a character is ready.
  718. X         Reads will be done in wait mode.  Use blanks to pad short
  719. X         strings. */
  720. X      tty_raw(1, char_mask);
  721. X         while(end_state != 'd') {
  722. X            fflush(stdout);
  723. X            if (!read(fileno(stdin), keybuf, 1)) break;
  724. X            keybuf[0] &= char_mask;
  725. X            fresh_line();
  726. X               for (len = 1; len < fkmax; len++) {
  727. X                  keybuf[len] = '\0';
  728. X                  if (hex_output)
  729. X                     put_str(hex_expand_to(&keybuf[len - 1], 3));
  730. X                  else put_str(expand(&keybuf[len - 1]));
  731. X                  fflush(stdout);
  732. X                  if (!read(fileno(stdin), &keybuf[len], 1)) break;
  733. X                  keybuf[len] &= char_mask;
  734. X               }
  735. X            /* come here when typing stops */
  736. X            keybuf[len] = '\0';
  737. X            if (found_match(keybuf, hex_output, 1)) continue;
  738. X            /* backup over the blanks */
  739. X               for ( ; len; keybuf[--len] = '\0')
  740. X                  if (keybuf[len - 1] != ' ') break;
  741. X            if (len == 0) continue;
  742. X            if (found_match(keybuf, hex_output, 1)) continue;
  743. X            if (found_exit(keybuf, hex_output, 1)) break;
  744. X         }
  745. X#else
  746. X      /* use this code if your OS can tell if a character is ready.
  747. X         Reads will be done by read_key() defined in sysdep.c */
  748. X      tty_raw(0, char_mask);
  749. X         while(end_state != 'd') {
  750. X            read_key(keybuf, fkmax);
  751. X            fresh_line();
  752. X            if (found_match(keybuf, hex_output, 0)) continue;
  753. X            if (found_exit(keybuf, hex_output, 0)) break;
  754. X         }
  755. X#endif
  756. X      if (keypad_local) putp(keypad_local);
  757. X      keys_tested(0, hex_output);
  758. X      if (has_meta_key)
  759. X         {
  760. X            if (char_mask != ALLOW_PARITY)
  761. X               {
  762. X                  if (tty_meta_prep()) (void) wait_here();
  763. X               }
  764. X            ptext("Begin meta key test. (km) (smm) (rmm)  Hit any key");
  765. X            ptext(" with the meta key.  The character will be");
  766. X            ptext(" displayed in hex.  If the meta key is working");
  767. X            ptext(" then the most significant bit will be set.  Type");
  768. X            ptextln(" 'end' to exit.");
  769. X            tty_raw(1, ALLOW_PARITY);
  770. X            putp(meta_on);
  771. X
  772. X               for (i = j = k = len = 0; i != 'e' | j != 'n' | k != 'd'; ) {
  773. X                  i = j;  j = k;
  774. X                  k = getchp(ALLOW_PARITY);
  775. X                  if (k == EOF) break;
  776. X                  if ((len += 3) >= columns)
  777. X                     {
  778. X                        put_crlf();  len = 3;
  779. X                     }
  780. X                  sprintf(outbuf, "%02X ", k);
  781. X                  put_str(outbuf);
  782. X                  k &= STRIP_PARITY;
  783. X               }
  784. X            putp(meta_off);
  785. X            put_crlf();
  786. X         }
  787. X      else
  788. X         {
  789. X            ptextln("This terminal has no meta key. (km)");
  790. X            (void) wait_here();
  791. X         }
  792. X      tty_set();
  793. X
  794. X#ifdef SVR3
  795. X      new_test(8);
  796. X      sprintf(temp, "Your terminal has %d labels (nlab) that are %d characters wide (lw) and %d lines high (lh)",
  797. X      num_labels, label_width, label_height);
  798. X      ptext(temp);
  799. X      ptextln(" Testing (smln) (pln) (rmln)");
  800. X      if (label_on) putp(label_on);
  801. X      if (label_width <= 0) label_width = sizeof(outbuf) - 1;
  802. X         for (i = 1; i <= num_labels; i++) {
  803. X            sprintf(outbuf, "L%d..............................", i);
  804. X            outbuf[label_width] = '\0';
  805. X            putp(tparm(plab_norm, i, outbuf));
  806. X         }
  807. X      (void) wait_here();
  808. X      if (label_off) putp(label_off);
  809. X#endif
  810. X
  811. X#ifndef TESTCAP
  812. X      new_test(8);
  813. X      fk = 1;  /* use function key 1 for now */
  814. X      if (pkey_xmit)
  815. X         {
  816. X            char mm[256];
  817. X
  818. X            /* test program function key */
  819. X            sprintf(temp,
  820. X               "(pfx) Set function key %d to transmit abc\\n", fk);
  821. X            ptextln(temp);
  822. X            putp(tparm(pkey_xmit, fk, "abc\n"));
  823. X            sprintf(temp, "Hit function key %d\n", fk);
  824. X            ptextln(temp);
  825. X               for (i = 0; i < 4; ++i) mm[i] = getchp(STRIP_PARITY);
  826. X            mm[i] = '\0';
  827. X            put_crlf();
  828. X            if (mm[0] != 'a' | mm[1] != 'b' | mm[2] != 'c')
  829. X               {
  830. X                  sprintf(temp, "Error string recieved was: %s", expand(mm));
  831. X                  ptextln(temp);
  832. X               }
  833. X            else putln("Thank you\n");
  834. X            /* if the terminal sent too much, flush it */
  835. X            if (tty_can_sync) (void) tty_sync_error();
  836. X         }
  837. X      else ptextln("Function key transmit (pfx), not present.");
  838. X
  839. X      if (pkey_local)
  840. X         {
  841. X            /* test local function key */
  842. X            sprintf(temp,
  843. X               "(pfloc) Set function key %d to execute a clear and print \"Done!\"", fk);
  844. X            ptextln(temp);
  845. X            sprintf(temp, "%sDone!", liberated(clear_screen));
  846. X            putp(tparm(pkey_local, fk, temp));
  847. X            sprintf(temp, "Hit function key %d.  Then hit return.", fk);
  848. X            ptextln(temp);
  849. X         }
  850. X      else ptextln("Function key execute local (pfloc), not present.");
  851. X
  852. X      (void) wait_here();
  853. X      /* if the terminal sent anything else, flush it */
  854. X      if (tty_can_sync) (void) tty_sync_error();
  855. X      if (key_f1 && pkey_xmit) putp(tparm(pkey_xmit, fk, key_f1));
  856. X#endif
  857. X   }
  858. X
  859. X
  860. Xtest_printer()
  861. X   {  /* test the printer commands */
  862. X
  863. X      if (stop_testing)
  864. X         {
  865. X            can_test("(mc4)(mc5)(mc0)(mc5i)");
  866. X            return;
  867. X         }
  868. X      put_clear();
  869. X      putln("Begin printer test.");
  870. X      if (!prtr_on || !prtr_off)
  871. X         {
  872. X            ptextln("Printer on/off missing. (mc5) (mc4)");
  873. X         }
  874. X      else
  875. X#if defined(SVR3) || defined(XENIX)
  876. X      if (prtr_silent)
  877. X         {
  878. X            ptextln("Your printer is silent. (mc5i) is set.");
  879. X            putp(prtr_on);
  880. X            ptextln("This line should be on the printer but not your screen. (mc5)");
  881. X            putp(prtr_off);
  882. X            ptextln("This line should be only on the screen. (mc4)");
  883. X         }
  884. X      else
  885. X         {
  886. X            ptextln("Your printer is not silent. (mc5i) is reset.");
  887. X            putp(prtr_on);
  888. X            ptextln("This line should be on the printer and the screen. (mc5)");
  889. X            putp(prtr_off);
  890. X            ptextln("This line should only be on the screen. (mc4)");
  891. X         }
  892. X#else
  893. X         {
  894. X            putp(prtr_on);
  895. X            ptextln("This line should be on the printer. (mc5)");
  896. X            putp(prtr_off);
  897. X            ptextln("This line should only be on the screen. (mc4)");
  898. X         }
  899. X#endif
  900. X      (void) wait_here();
  901. X      if (print_screen)
  902. X         {
  903. X            ptext("I am going to send the contents of the screen to");
  904. X            ptext(" the printer, then wait for a keystroke from you.");
  905. X            ptext("  All of the text that appears on the screen");
  906. X            ptextln(" should be printed. (mc0)");
  907. X            putp(print_screen);
  908. X            (void) wait_here();
  909. X         }
  910. X      putln("End of printer test.");
  911. X   }
  912. X
  913. X
  914. Xstatic void
  915. Xline_pattern()
  916. X   {  /* put up a pattern that will help count the number of lines */
  917. X      int i, j;
  918. X
  919. X      put_clear();
  920. X      if (over_strike)
  921. X         for (i = 0; i < 100; i++) {
  922. X            if (i) put_crlf();
  923. X               for (j = i / 10; j; j--) put_this(' ');
  924. X            put_this('0' + ((i + 1) % 10));
  925. X         }
  926. X      else  /* I assume it will scroll */
  927. X         for (i = 100; i; i--) {
  928. X            sprintf(temp, "\r\n%d", i);
  929. X            put_str(temp);
  930. X         }
  931. X   }
  932. X
  933. X
  934. Xstatic void
  935. Xcolumn_pattern()
  936. X   {  /* put up at pattern that will help count the number of columns */
  937. X      int i, j;
  938. X
  939. X      put_clear();
  940. X         for (i = 0; i < 20; i++) {
  941. X               for (j = 1; j < 10; j++) {
  942. X                  put_this('0' + j);
  943. X               }
  944. X            put_this('.');
  945. X         }
  946. X   }
  947. X
  948. X
  949. Xtest_report(crx, hex_display)
  950. Xint crx, hex_display;
  951. X   {  /* status report and echo test */
  952. X      int i, j, ch, crp, high_bit, save_scan_mode;
  953. X      char buf[1024];
  954. X      char txt[8];
  955. X
  956. X      put_clear();
  957. X      if (crx == 1)
  958. X         {
  959. X            ptext("Characters after a CR or LF will be echoed as");
  960. X            ptext(" is.  All other characters will be expanded.  Type");
  961. X            ptext(" 'end' to exit.  Type");
  962. X            ptext(" 'echo' to redisplay last report.  Type");
  963. X            ptext(" 'hex' to redisplay last report in hex.  Type");
  964. X            ptextln(" 'clear' to clear screen.");
  965. X         }
  966. X      else /* echo test */
  967. X         {
  968. X            ptext("Begin echo test.  Type");
  969. X            ptext(" 'end' to exit.  Type");
  970. X            ptext(" 'hex' to display characters in hex.  Type");
  971. X            ptext(" 'high' to toggle high order bit on output.  Type");
  972. X            ptextln(" 'clear' to clear screen.");
  973. X         }
  974. X      txt[sizeof(txt) - 1] = '\0';
  975. X      save_scan_mode = scan_mode;
  976. X      tty_raw(1, char_mask);
  977. X         for (i = crp = high_bit = 0; ; ) {
  978. X            ch = getchp(char_mask);
  979. X            if (ch == EOF) break;
  980. X            if (i >= sizeof(buf) - 1) i = 0;
  981. X            buf[i++] = ch;
  982. X            buf[i] = '\0';
  983. X               for (j = 0; j < sizeof(txt) - 1; j++) {
  984. X                  txt[j] = txt[j + 1];
  985. X               }
  986. X            txt[sizeof(txt) - 1] = ch & STRIP_PARITY;
  987. X            if (crx == 0) /* echo test */
  988. X               {
  989. X                  if (hex_display) ptext(hex_expand_to(&buf[i - 1], 3));
  990. X                  else putch(ch | high_bit);
  991. X               }
  992. X            else /* status report test */
  993. X            if (ch == '\n' | ch == '\r')
  994. X               {
  995. X                  put_crlf();
  996. X                  crp = 0;
  997. X               }
  998. X            else
  999. X            if (crp++ < crx) putch(ch | high_bit);
  1000. X            else put_str(expand(&buf[i - 1]));
  1001. X            if (!strncmp(&txt[sizeof(txt) - 7], "columns", 7))
  1002. X               {
  1003. X                  column_pattern();
  1004. X                  buf[i = 0] = '\0';
  1005. X                  crp = 0;
  1006. X               }
  1007. X            if (!strncmp(&txt[sizeof(txt) - 5], "lines", 5))
  1008. X               {
  1009. X                  line_pattern();
  1010. X                  buf[i = 0] = '\0';
  1011. X                  crp = 0;
  1012. X               }
  1013. X            if (!strncmp(&txt[sizeof(txt) - 5], "clear", 5))
  1014. X               {
  1015. X                  put_clear();
  1016. X                  buf[i = 0] = '\0';
  1017. X                  crp = 0;
  1018. X               }
  1019. X            if (!strncmp(&txt[sizeof(txt) - 4], "high", 4))
  1020. X               {
  1021. X                  high_bit ^= 0x80;
  1022. X                  if (high_bit) ptextln("\nParity bit set");
  1023. X                  else ptextln("\nParity bit reset");
  1024. X               }
  1025. X            if (!strncmp(&txt[sizeof(txt) - 4], "echo", 4))
  1026. X               {
  1027. X                  /* display the last status report */
  1028. X                  /* clear bypass condition on Tek terminals */
  1029. X                  put_crlf();
  1030. X                  buf[i -= 4] = '\0';
  1031. X                  put_str(expand(buf));
  1032. X               }
  1033. X            if (save_scan_mode &&
  1034. X               !strncmp(&txt[sizeof(txt) - 4], "scan", 4))
  1035. X               {
  1036. X                  /* toggle scan mode */
  1037. X                  scan_mode = !scan_mode;
  1038. X               }
  1039. X            if (!strncmp(&txt[sizeof(txt) - 3], "end", 3)) break;
  1040. X            if (!strncmp(&txt[sizeof(txt) - 3], "hex", 3))
  1041. X               if (crx)
  1042. X                  {
  1043. X                     /* display the last status report */
  1044. X                     /* clear bypass condition on Tek terminals */
  1045. X                     put_crlf();
  1046. X                     buf[i -= 3] = '\0';
  1047. X                     put_str(hex_expand_to(buf, 3));
  1048. X                  }
  1049. X               else hex_display = !hex_display;
  1050. X            if (!strncmp(&txt[sizeof(txt) - 3], "two", 3)) crx = 2;
  1051. X            if (!strncmp(&txt[sizeof(txt) - 3], "one", 3)) crx = 1;
  1052. X            if (!strncmp(&txt[sizeof(txt) - 3], "all", 3)) crx = 0;
  1053. X         }
  1054. X      scan_mode = save_scan_mode;
  1055. X      put_crlf();
  1056. X      tty_set();
  1057. X      if (crx) ptextln("End of status report test.");
  1058. X      else ptextln("End of echo test.");
  1059. X   }
  1060. X
  1061. X
  1062. Xstatic int
  1063. Xpack_ansi()
  1064. X   {  /* read and pack an ANSI character */
  1065. X      int ch;
  1066. X
  1067. X      if (*pch) return *pch++;
  1068. X
  1069. X         while (1) {
  1070. X            ch = getchp(char_mask);
  1071. X            if (ch == EOF) return EOF;
  1072. X            if (ch == A_DC1 || ch == A_DC3) continue;
  1073. X            *ach++ = ch;  *ach = '\0';
  1074. X            if (got_escape && ch >= ' ')
  1075. X               {
  1076. X                  got_escape = 0;
  1077. X                  if (ch < '@' || ch > '_')
  1078. X                     {
  1079. X                        *pch++ = A_ESC;
  1080. X                        *pch = ch;
  1081. X                        pch[1] = '\0';
  1082. X                        return A_ESC;
  1083. X                     }
  1084. X                  ch += 0x40;
  1085. X                  break;
  1086. X               }
  1087. X            else
  1088. X            if (ch == A_ESC) got_escape = 1;
  1089. X            else break;
  1090. X         }
  1091. X      *pch++ = ch;  *pch = '\0';
  1092. X      return ch;
  1093. X   }
  1094. X
  1095. X
  1096. Xstatic void
  1097. Xread_ansi()
  1098. X   {  /* read an ANSI status report */
  1099. X      int ch;
  1100. X
  1101. X      fflush(stdout);
  1102. X      ach = ansi_buf;  pch = pack_buf;
  1103. X      ansi_buf[0] = pack_buf[0] = '\0';
  1104. X      got_escape = 0;
  1105. X      ch = pack_ansi();
  1106. X      if (ch == A_ESC)
  1107. X         do {
  1108. X            ch = pack_ansi();
  1109. X            if (ch == EOF) return;
  1110. X         } while (ch < '0' || ch > '~');
  1111. X      else
  1112. X      if (ch == A_CSI)
  1113. X         do {
  1114. X            ch = pack_ansi();
  1115. X            if (ch == EOF) return;
  1116. X         } while (ch < '@' || ch > '~');
  1117. X      else
  1118. X      if (ch == A_DCS)
  1119. X         do {
  1120. X            ch = pack_ansi();
  1121. X            if (ch == EOF) return;
  1122. X         } while (ch != A_ST);
  1123. X      return;
  1124. X   }
  1125. X
  1126. X
  1127. Xstatic int
  1128. Xvalid_mode(expected)
  1129. Xint expected;
  1130. X   {  /* read a terminal mode status report and parse the result */
  1131. X      char *s;
  1132. X      int ch, terminator;
  1133. X
  1134. X      read_ansi();
  1135. X
  1136. X      ape = 0;
  1137. X      ch = pack_buf[0] & 0xff;
  1138. X      if (ch != A_CSI && ch != A_DCS) return FALSE;
  1139. X
  1140. X      s = pack_buf + 1;
  1141. X      private_use = 0;
  1142. X      if (*s >= '<' & *s <= '?') private_use = *s++;
  1143. X      ansi_value[0] = 0;
  1144. X      terminator = 0;
  1145. X         for ( ; ch = *s; s++) {
  1146. X            if (ch >= '0' && ch <= '9')
  1147. X               ansi_value[ape] = ansi_value[ape] * 10 + ch - '0';
  1148. X            else
  1149. X            if (ch == ';' || ch == ':')
  1150. X               ansi_value[++ape] = 0;
  1151. X            else
  1152. X            if (ch >= '<' && ch <= '?')
  1153. X               private_use = ch;
  1154. X            else
  1155. X            if (ch >= ' ')
  1156. X               terminator = (terminator << 8) | ch;
  1157. X            else break;
  1158. X         }
  1159. X      return terminator == expected;
  1160. X   }
  1161. X
  1162. X
  1163. Xstatic int
  1164. Xread_reports()
  1165. X   {  /* read all the reports in the ANSI report structure */
  1166. X      int i, j, k, tc, vcr, lc;
  1167. X      char *s;
  1168. X
  1169. X      lc = 5;
  1170. X      terminal_class = tc = 0;
  1171. X         for (i = 0; report_list[i].text; i++, lc++) {
  1172. X            if (terminal_class < report_list[i].lvl &&
  1173. X               tc < report_list[i].lvl)
  1174. X               {
  1175. X                  j = wait_here();
  1176. X                  if (j != 'c' && j != 'C') return j;
  1177. X                  tc = report_list[i].lvl;
  1178. X               }
  1179. X            else
  1180. X            if (lc >= lines)
  1181. X               {
  1182. X                  (void) wait_here();
  1183. X                  lc = 1;
  1184. X               }
  1185. X            sprintf(temp, "%s (%s) ", report_list[i].text,
  1186. X               expand_command(report_list[i].request));
  1187. X            ptext(temp);
  1188. X               for (j = strlen(temp); j < 49; j++) putchp(' ');
  1189. X            putp(report_list[i].request);
  1190. X            vcr = 0;
  1191. X            if (report_list[i].final == 0) read_ansi();
  1192. X            else
  1193. X            if (valid_mode(report_list[i].final))
  1194. X               switch(report_list[i].final) {
  1195. X                  case 'c':
  1196. X                     terminal_class = ansi_value[0];
  1197. X                     break;
  1198. X                  case 'R':
  1199. X                     vcr = TRUE;
  1200. X                     break;
  1201. X               }
  1202. X            j = pack_buf[0] & 0xff;
  1203. X            if (j == A_CSI || j == A_DCS)
  1204. X               {
  1205. X                  s = expand(ansi_buf);
  1206. X                  if (char_count + expand_chars >= columns)
  1207. X                     {
  1208. X                        put_str("\r\n        ");
  1209. X                        lc++;
  1210. X                     }
  1211. X                  put_str(s);
  1212. X               }
  1213. X            put_crlf();
  1214. X            if (vcr)
  1215. X               {  /* find out how big the screen is */
  1216. X                  putp(report_list[i].request);
  1217. X                  if (!valid_mode('R')) continue;
  1218. X                  j = ansi_value[0];
  1219. X                  k = ansi_value[1];
  1220. X                  putp("\033[255B\033[255C\033[6n");
  1221. X                  if (!valid_mode('R')) continue;
  1222. X                  sprintf(temp, "\033[%d;%dH", j, k);
  1223. X                  putp(temp);
  1224. X                  ptext("(DSR) Screen size (CSI 6 n)");
  1225. X                     for (j = char_count; j < 50; j++) putchp(' ');
  1226. X                  sprintf(temp, "%d x %d", ansi_value[1], ansi_value[0]);
  1227. X                  ptextln(temp);
  1228. X                  
  1229. X               }
  1230. X         }
  1231. X      return wait_here();
  1232. X   }
  1233. X
  1234. X
  1235. Xstatic int
  1236. Xrequest_cfss()
  1237. X   {  /* Request Control function selection or settings */
  1238. X      int i, j, k, l, ch;
  1239. X      char *s;
  1240. X
  1241. X      put_clear();
  1242. X      ptextln("Request                         Expected  Received");
  1243. X      put_crlf();
  1244. X         for (i = 0; rqss[i].text; i++) {
  1245. X            ptext(rqss[i].text);
  1246. X            j = strlen(rqss[i].text) + strlen(rqss[i].expect);
  1247. X            putchp(' ');
  1248. X               for (j++; j < 40; j++) putchp(' ');
  1249. X            ptext(rqss[i].expect);
  1250. X            putchp(' ');
  1251. X            putp(rqss[i].set_mode);
  1252. X            sprintf(temp, "\033P$q%s\033\\", rqss[i].request);
  1253. X            putp(temp);
  1254. X            read_ansi();
  1255. X            putp(rqss[i].reset_mode);
  1256. X            putchp(' ');
  1257. X               for (j = 0; ansi_buf[j]; j++) {
  1258. X                  if (ansi_buf[j] == 'r')
  1259. X                     {
  1260. X                           for (k = j++; ch = (ansi_buf[k] & 0xff); k++)
  1261. X                              if (ch == A_ESC) break;
  1262. X                              else
  1263. X                              if (ch == A_ST) break;
  1264. X                        ansi_buf[k] = '\0';
  1265. X                        s = expand(&ansi_buf[j]);
  1266. X                        if (char_count + expand_chars >= columns)
  1267. X                           put_str("\r\n        ");
  1268. X                        put_str(s);
  1269. X                     }
  1270. X               }
  1271. X            put_crlf();
  1272. X         }
  1273. X      /* calculate the valid attributes */
  1274. X      ptext("Valid attributes:         0");
  1275. X      j = 0;
  1276. X         for (i = 1; i < 20; i++) {
  1277. X            sprintf(temp, "\033[0;%dm\033P$qm\033\\", i);
  1278. X            putp(temp);
  1279. X            (void) valid_mode('m');
  1280. X            if (ape > 0)
  1281. X               {
  1282. X                  j = i;
  1283. X                  sprintf(temp, "\033[0m; %d", i);
  1284. X                  putp(temp);
  1285. X               }
  1286. X         }
  1287. X      put_crlf();
  1288. X      /* calculate how many parameters can be sent */
  1289. X      ptext("Max number of parameters: ");
  1290. X      sprintf(temp, "%dm\033P$qm\033\\", j);
  1291. X      l = -1;
  1292. X      if (j > 0)
  1293. X         for (l = 1; l < 33; l++ ) {
  1294. X            putp("\033[0");
  1295. X               for (ch = 1; ch <= l; ch++) put_this(';');
  1296. X            putp(temp);
  1297. X            (void) valid_mode('m');
  1298. X            if (ape == 0) break;
  1299. X         }
  1300. X      putp("\033[m");
  1301. X      if (l >= 0)
  1302. X         {
  1303. X            sprintf(temp, "%d", l);
  1304. X            ptext(temp);
  1305. X         }
  1306. X      else ptext("unknown");
  1307. X      put_crlf();
  1308. X      return wait_here();
  1309. X   }
  1310. X
  1311. X
  1312. Xstatic
  1313. Xmode_display(p, n, c, s, r)
  1314. Xchar *p;
  1315. Xchar n, c, s, r;
  1316. X   {   /* print the mode display entry */
  1317. X      int k;
  1318. X
  1319. X      sprintf(temp, "%s%d (%c, %c, %c)", p, n, c, s, r);
  1320. X      k = strlen(temp);
  1321. X      if (char_count + k >= columns) put_crlf();
  1322. X         for ( ; k < 14; k++) putchp(' ');
  1323. X      put_str(temp);
  1324. X   }
  1325. X
  1326. X
  1327. Xstatic void
  1328. Xterminal_state()
  1329. X   {  /* test DECRQM status reports */
  1330. X      int i, j, k, l, modes_found;
  1331. X      char *s;
  1332. X      char buf[256], tms[256];
  1333. X      char mode_puc[MAX_MODES], mode_number[MAX_MODES];
  1334. X      char set_value[MAX_MODES], reset_value[MAX_MODES];
  1335. X      char current_value[MAX_MODES];
  1336. X
  1337. X      ptext("Testing terminal mode status. (CSI 0 $ p)");
  1338. X      putp("\033[0$p");
  1339. X      modes_found = 0;
  1340. X      tms[0] = '\0';
  1341. X      if (valid_mode(('$' << 8) | 'y'))
  1342. X         for (i = 0; puc[i]; i++) {
  1343. X            put_crlf();
  1344. X            if (i)
  1345. X               {
  1346. X                  sprintf(temp, "Private use: %c", puc[i][0]);
  1347. X               }
  1348. X            else strcpy(temp, "Standard modes:");
  1349. X            k = strlen(temp);
  1350. X            ptext(temp);
  1351. X               for (j = 0; j < sizeof(buf); buf[j++] = ' ');
  1352. X               for (j = l = 0; j < 255 && j - l < 50; j++) {
  1353. X                  sprintf(temp, "\033[%s%d$p", puc[i], j);
  1354. X                  putp(temp);
  1355. X                  if (!valid_mode(('$' << 8) | 'y'))
  1356. X                     {  /* not valid, save terminating value */
  1357. X                        s = expand(ansi_buf);
  1358. X                        sprintf(tms, "%s%s%d %s  ", tms, puc[i], j, s);
  1359. X                        break;
  1360. X                     }
  1361. X                  if (private_use != puc[i][0]) break;
  1362. X                  if (ansi_value[0] != j) break;
  1363. X                  if (ansi_value[1])
  1364. X                     {
  1365. X                        l = j;
  1366. X                        if (k > 70)
  1367. X                           {
  1368. X                              buf[k] = '\0';
  1369. X                              put_crlf();
  1370. X                              ptextln(buf);
  1371. X                                 for (k = 0; k < sizeof(buf); )
  1372. X                                    buf[k++] = ' ';
  1373. X                              k = 0;
  1374. X                           }
  1375. X                        sprintf(temp, " %d", j);
  1376. X                        ptext(temp);
  1377. X                        k += strlen(temp);
  1378. X                        buf[k - 1] = ansi_value[1] + '0';
  1379. X                        if (modes_found >= MAX_MODES) continue;
  1380. X                        current_value[modes_found] =
  1381. X                           ansi_value[1] + '0';
  1382. X                        /* some modes never return */
  1383. X                        if ((i == 0 && j == 13) /* control execution */
  1384. X                           || (puc[i][0] == '?' && j == 2)) /* VT52 */
  1385. X                           set_value[modes_found] =
  1386. X                              reset_value[modes_found] = '-';
  1387. X                        else set_value[modes_found] =
  1388. X                           reset_value[modes_found] = ' ';
  1389. X                        mode_puc[modes_found] = i;
  1390. X                        mode_number[modes_found++] = j;
  1391. X                     }
  1392. X               }
  1393. X            buf[k] = '\0';
  1394. X            if (buf[k - 1] != ' ')
  1395. X               {
  1396. X                  put_crlf();
  1397. X                  ptext(buf);
  1398. X               }
  1399. X         }
  1400. X      if (i = modes_found)
  1401. X         {
  1402. X            put_crlf();
  1403. X            put_crlf();
  1404. X            if (tms[0]) ptextln(tms);
  1405. X            ptext("Hit 'Y' to test mode set/reset states.");
  1406. X            i = wait_here();
  1407. X         }
  1408. X      if (i == 'y' || i == 'Y')
  1409. X         while (1) {
  1410. X#ifdef STATUSFIX
  1411. X            FILE *fp;
  1412. X
  1413. X#ifdef TEDANSI
  1414. X            fp = fopen("ted.ansi", "w");
  1415. X#else
  1416. X            fp = fopen("/dev/console", "w");
  1417. X#endif
  1418. X#endif
  1419. X               for (i = j = 0; j < modes_found; j = ++i >> 1) {
  1420. X                  if (set_value[j] == '-') continue;
  1421. X                  k = (current_value[j] ^ i) & 1;
  1422. X                  sprintf(temp, "\033[%s%d%c\033[%s%d$p",
  1423. X                     puc[mode_puc[j]], mode_number[j],
  1424. X                     k ? 'l' : 'h',
  1425. X                     puc[mode_puc[j]], mode_number[j]);
  1426. X#ifdef STATUSFIX
  1427. X                  if (fp)
  1428. X                     {
  1429. X                        fprintf(fp, "%s\n", expand(temp));
  1430. X                        fflush(fp);
  1431. X                     }
  1432. X#endif
  1433. X                  putp(temp);
  1434. X                  if (!valid_mode(('$' << 8) | 'y')) continue;
  1435. X                  if (k) reset_value[j] = ansi_value[1] + '0';
  1436. X                  else set_value[j] = ansi_value[1] + '0';
  1437. X               }
  1438. X            put_str("\033[30l");  /* added for GORT bug (WY-185) */
  1439. X#ifdef STATUSFIX
  1440. X            if (fp) fclose(fp);
  1441. X#endif
  1442. X            tty_set();
  1443. X            /* print the results */
  1444. X            put_clear();
  1445. X            putln("mode (initial, set, reset)");
  1446. X               for (j = 0; j < modes_found; j++) {
  1447. X                  mode_display(puc[mode_puc[j]], mode_number[j],
  1448. X                     current_value[j], set_value[j], reset_value[j]);
  1449. X               }
  1450. X            ptext("\n\nHit 'R' to repeat test.  'S' to sort results.");
  1451. X            i = wait_here();
  1452. X            if (i == 's' || i == 'S')
  1453. X               {  /* print the same stuff, sorted by current_value */
  1454. X                  put_crlf();
  1455. X                     for (i = '1'; i <= '4'; i++) {
  1456. X                           for (j = 0; j < modes_found; j++) {
  1457. X                              if (current_value[j] == i)
  1458. X                                 mode_display(puc[mode_puc[j]],
  1459. X                                    mode_number[j], current_value[j],
  1460. X                                    set_value[j], reset_value[j]);
  1461. X                           }
  1462. X                     }
  1463. X                  ptext("\n\nHit 'R' to repeat test.");
  1464. X                  i = wait_here();
  1465. X               }
  1466. X            if (i != 'r' && i != 'R') break;
  1467. X            tty_raw(1, char_mask);
  1468. X         }
  1469. X      else tty_set();
  1470. X   }
  1471. X
  1472. X
  1473. Xtest_ansi_reports()
  1474. X   {  /* test ansi status reports */
  1475. X      int i;
  1476. X
  1477. X      put_clear();
  1478. X      ptext("Begin ANSI status report testing. ");
  1479. X      ptext(" Parity bit set will be displayed in reverse video. ");
  1480. X      ptextln(" If the terminal hangs, hit any alphabetic key.");
  1481. X      put_crlf();
  1482. X      tty_raw(1, char_mask);
  1483. X
  1484. X         do {
  1485. X            i = read_reports();
  1486. X         } while(i == 'r' || i == 'R');
  1487. X
  1488. X      if (terminal_class >= 63)
  1489. X         {
  1490. X               do {
  1491. X                  i = request_cfss();
  1492. X               } while(i == 'r' || i == 'R');
  1493. X            terminal_state();
  1494. X         }
  1495. X      else tty_set();
  1496. X
  1497. X      putln("\nEnd of ANSI status report test.");
  1498. X      (void) wait_here();
  1499. X   }
  1500. X
  1501. X
  1502. Xstatic void
  1503. Xselect_bank(bank)
  1504. Xchar *bank;
  1505. X   {  /* select a graphics character set for ANSI terminals */
  1506. X      putp(bank);
  1507. X      switch (bank[1] & 3) {
  1508. X      case 0:
  1509. X         putchp('O' & 0x1f);  /* control O */
  1510. X         break;
  1511. X      case 1:
  1512. X         putchp('N' & 0x1f);  /* control N */
  1513. X         putp("\033~");
  1514. X         break;
  1515. X      case 2:
  1516. X         putp("\033n\033}");
  1517. X         break;
  1518. X      case 3:
  1519. X         putp("\033o\033|");
  1520. X         break;
  1521. X      }
  1522. X   }
  1523. X
  1524. X
  1525. Xstatic void
  1526. Xshow_characters(bank, bias)
  1527. Xchar *bank;
  1528. Xint bias;
  1529. X   {  /* print the ANSI graphics characters */
  1530. X      int i;
  1531. X
  1532. X      sprintf(temp, "G%d GL   ", bank[1] & 3);
  1533. X      ptext(temp);
  1534. X      select_bank(bank);
  1535. X         for (i = ' '; i < 0x80; i++) {
  1536. X            if (char_count >= columns ||
  1537. X               (i != ' ' && (i & 31) == 0)) put_str("\n        ");
  1538. X            putchp(i + bias);
  1539. X         }
  1540. X      select_bank(default_bank);
  1541. X      put_str("   DEL <");
  1542. X      select_bank(bank);
  1543. X      putchp(0x7f + bias);
  1544. X      select_bank(default_bank);
  1545. X      putchp('>');
  1546. X      put_crlf();
  1547. X      put_crlf();
  1548. X   }
  1549. X
  1550. X
  1551. X/* ANSI graphics test
  1552. X        94     96   character sets
  1553. X   G0   (      ,
  1554. X   G1   )      -
  1555. X   G2   *      .
  1556. X   G3   +      /
  1557. X
  1558. XStandard Definitions
  1559. X   A    UK
  1560. X   B    US ASCII
  1561. X
  1562. XDec extended definitions
  1563. X   0    Special graphics
  1564. X   
  1565. X */
  1566. X
  1567. Xansi_graphics()
  1568. X   {  /* test ANSI character sets */
  1569. X      int j, ch;
  1570. X      char bank[32];
  1571. X
  1572. X      put_clear();
  1573. X      ptext("Enter the bank ()*+,-./ followed by the character set");
  1574. X      ptext(" 0123456789:;<=>? for private use, and");
  1575. X      ptextln(" @A...Z[\\]^_`a...z{|}~ for standard sets.");
  1576. X      strcpy(bank, "\033)0");
  1577. X         for ( ; bank[0]; ) {
  1578. X            put_crlf();
  1579. X            show_characters(bank, 0);
  1580. X            /* G0 will not print in GR */
  1581. X            if (bank[1] & 3) show_characters(bank, 0x80);
  1582. X               for (j = 1; ch = getchp(char_mask); j++) {
  1583. X                  if (ch == EOF) break;
  1584. X                  putchp(ch);
  1585. X                  if (j == 1 && ch > '/') j++;
  1586. X                  bank[j] = ch;
  1587. X                  if (ch < ' ' | ch > '/') break;
  1588. X                  if (j + 1 >= sizeof(bank)) break;
  1589. X               }
  1590. X            if (j == 1) break;
  1591. X            if (bank[j] < '0' || bank[j] > '~') break;
  1592. X            bank[j + 1] = '\0';
  1593. X         }
  1594. X   }
  1595. END_OF_FILE
  1596. if test 44721 -ne `wc -c <'fun.c'`; then
  1597.     echo shar: \"'fun.c'\" unpacked with wrong size!
  1598. fi
  1599. # end of 'fun.c'
  1600. fi
  1601. echo shar: End of archive 1 \(of 7\).
  1602. cp /dev/null ark1isdone
  1603. MISSING=""
  1604. for I in 1 2 3 4 5 6 7 ; do
  1605.     if test ! -f ark${I}isdone ; then
  1606.     MISSING="${MISSING} ${I}"
  1607.     fi
  1608. done
  1609. if test "${MISSING}" = "" ; then
  1610.     echo You have unpacked all 7 archives.
  1611.     rm -f ark[1-9]isdone
  1612. else
  1613.     echo You still need to unpack the following archives:
  1614.     echo "        " ${MISSING}
  1615. fi
  1616. ##  End of shell archive.
  1617. exit 0
  1618.  
  1619. exit 0 # Just in case...
  1620. -- 
  1621. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1622. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1623. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1624. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1625.